<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" >

  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/turbolinks/5.2.0/turbolinks.js" integrity="sha256-iM4Yzi/zLj/IshPWMC1IluRxTtRjMqjPGd97TZ9yYpU=" crossorigin="anonymous"></script>
  <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
  <link href="https://fonts.googleapis.com/css?family=Cousine|Inconsolata" rel="stylesheet">
  <link rel="shortcut icon" type="image/png" href="/favicon.png">

  <link rel="stylesheet" href="/css/style.css">
  <link rel="stylesheet" href="/css/css/fontawesome-all.min.css">
  <link rel="stylesheet" href="/css/css/work-sans-v7.css">
  <script src="/js/main.js"></script>

  <!-- Begin Jekyll SEO tag v2.6.1 -->
<title>Streaming blockchain transactions | Hive Developer</title>
<meta name="generator" content="Jekyll v4.0.0" />
<meta property="og:title" content="Streaming blockchain transactions" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="Including virtual operations when streaming blockchain transactions" />
<meta property="og:description" content="Including virtual operations when streaming blockchain transactions" />
<link rel="canonical" href="virtual-operations-when-streaming-blockchain-transactions.html" />
<meta property="og:url" content="virtual-operations-when-streaming-blockchain-transactions.html" />
<meta property="og:site_name" content="Hive Developer" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2020-08-26T11:52:22-07:00" />
<script type="application/ld+json">
{"description":"Including virtual operations when streaming blockchain transactions","mainEntityOfPage":{"@type":"WebPage","@id":"virtual-operations-when-streaming-blockchain-transactions.html"},"@type":"BlogPosting","url":"virtual-operations-when-streaming-blockchain-transactions.html","headline":"Streaming blockchain transactions","dateModified":"2020-08-26T11:52:22-07:00","datePublished":"2020-08-26T11:52:22-07:00","@context":"https://schema.org"}</script>
<!-- End Jekyll SEO tag -->


  
</head>
<body>
<header>
  <h1>
    <button type="button" class="open-nav" id="open-nav"></button>
    <a href="/"  class="logo-link"><img src="/images/logotype_black.svg" height="40" alt="Hive Developer logo"></a>
  </h1>

  
  <form action="/search/" method="get">
    <input type="text" name="q" id="search-input" placeholder="Search">
    <input type="submit" value="Search" style="display: none;">
  </form>
  

  <div id="sidebar" class="sidebar">
	
	
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/">
		<h6 class="ctrl-nav-section title">Introduction</h6>
		<ul class="cont-nav-section content">
			
				
					
					
						
						<li><a href="/#introduction-welcome">Welcome to Hive</a></li>
						
					
				
			
		</ul>
	</section>
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/quickstart/">
		<h6 class="ctrl-nav-section title">Quickstart</h6>
		<ul class="cont-nav-section content">
			
				
					
					
						
						<li><a href="/quickstart/#quickstart-choose-library">Choose Library</a></li>
						
					
						
						<li><a href="/quickstart/#quickstart-hive-full-nodes">Hive Nodes</a></li>
						
					
						
						<li><a href="/quickstart/#quickstart-testnet">Hive Testnet</a></li>
						
					
				
			
		</ul>
	</section>
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/tutorials/">
		<h6 class="ctrl-nav-section title">Tutorials</h6>
		<ul class="cont-nav-section content">
			
				
					
						<li><a href="/tutorials/#tutorials-javascript">Javascript</a></li>
					
				
					
						<li><a href="/tutorials/#tutorials-python">Python</a></li>
					
				
					
						<li><a href="/tutorials/#tutorials-ruby">Ruby</a></li>
					
				
					
						<li><a href="/tutorials/#tutorials-recipes">Recipes</a></li>
					
				
			
		</ul>
	</section>
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/services/">
		<h6 class="ctrl-nav-section title">Services</h6>
		<ul class="cont-nav-section content">
			
				
					
					
						
						<li><a href="/services/#services-hive-blog">hive.blog</a></li>
						
					
						
						<li><a href="/services/#services-hivesigner">HiveSigner</a></li>
						
					
						
						<li><a href="/services/#services-jussi">Jussi</a></li>
						
					
						
						<li><a href="/services/#services-imagehoster">ImageHoster</a></li>
						
					
						
						<li><a href="/services/#services-dhf">DHF</a></li>
						
					
				
			
		</ul>
	</section>
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/apidefinitions/">
		<h6 class="ctrl-nav-section title">Appbase API</h6>
		<ul class="cont-nav-section content">
			
				
					
					
						
						<li><a href="/apidefinitions/#apidefinitions-condenser-api">Condenser Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-bridge">Bridge</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-account-by-key-api">Account By Key Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-account-history-api">Account History Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-block-api">Block Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-database-api">Database Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-debug-node-api">Debug Node Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-follow-api">Follow Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-jsonrpc">Jsonrpc</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-market-history-api">Market History Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-network-broadcast-api">Network Broadcast Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-rc-api">Rc Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-reputation-api">Reputation Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-rewards-api">Rewards Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-tags-api">Tags Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-transaction-status-api">Transaction Status Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-witness-api">Witness Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-broadcast-ops">Broadcast Ops</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-broadcast-ops-communities">Broadcast Ops Communities</a></li>
						
					
				
			
		</ul>
	</section>
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/resources/">
		<h6 class="ctrl-nav-section title">Resources</h6>
		<ul class="cont-nav-section content">
			
				
					
					
						
						<li><a href="/resources/#resources-overview">Overview</a></li>
						
					
						
						<li><a href="/resources/#resources-client-libs">Client Libraries</a></li>
						
					
						
						<li><a href="/resources/#resources-bluepaper">Bluepaper</a></li>
						
					
						
						<li><a href="/resources/#resources-whitepaper">Whitepaper</a></li>
						
					
						
						<li><a href="/resources/#resources-tools">Tools</a></li>
						
					
						
						<li><a href="/resources/#resources-hivesigner-libs">Hivesigner Libs</a></li>
						
					
						
						<li><a href="/resources/#resources-hive-keychain">Hive Keychain</a></li>
						
					
						
						<li><a href="/resources/#resources-developeradvocate">Community & Help</a></li>
						
					
				
			
		</ul>
	</section>
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/glossary/">
		<h6 class="ctrl-nav-section title">Glossary</h6>
		<ul class="cont-nav-section content">
			
				
					
					
						
						<li><a href="/glossary/#glossary-chain-basics">Chain Basics</a></li>
						
					
						
					
						
						<li><a href="/glossary/#glossary-governance">Governance</a></li>
						
					
						
						<li><a href="/glossary/#glossary-transactions">Transactions</a></li>
						
					
						
						<li><a href="/glossary/#glossary-api">API</a></li>
						
					
						
						<li><a href="/glossary/#glossary-market">Market</a></li>
						
					
				
			
		</ul>
	</section>
	
</div>



  <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">
</header>
<div class="main" id="top">
  <div class="hero">
    <h1 class="hero__h1">Hive Developer Portal </h1>
    <img class="hero__img" src="/images/honey-comb-92.png" style="position: relative; top: 10px;" />
  </div>
  <section id="tutorials-recipes-virtual-operations-when-streaming-blockchain-transactions" class="row tutorials-recipes-virtual-operations-when-streaming-blockchain-transactions">
	<h3>
		<a id="tutorials-recipes-virtual-operations-when-streaming-blockchain-transactions">
			Streaming blockchain transactions
			
		</a>
	</h3>
	
		<span class="description"><p>Including virtual operations when streaming blockchain transactions</p>
</span>
	

	<p>This recipe will take you through the process of streaming blockchain transactions, both from <code class="highlighter-rouge">head_block_num</code> and <code class="highlighter-rouge">last_irreversible_block_num</code>, and explain the presence/absence of virtual operations in the streamed transactions.</p>

<h2 id="intro">Intro</h2>

<p>There are two points from which Steem blockchain transactions can be streamed to give a “live” view of what’s happening on the blockchain. The first is from the <code class="highlighter-rouge">head block</code> which is the most recent block created on the chain (every 3 seconds when a new block is created). The second, is from the <code class="highlighter-rouge">last irreversible block</code> which is the newest block that has been confirmed by a sufficient number of block producers so that it can no longer be invalidated. This is not a live view but it is normally not far behind the head block number.</p>

<p>There is already a <a href="https://developers.steem.io/tutorials-javascript/stream_blockchain_transactions">javascript tutorial</a> on the <a href="https://developers.steem.io/">devportal</a> describing how to stream blockchain transactions. This recipe will go into further detail on operations on each block and more specifically the virtual operations that are executed with every new block. We will also assume that you have already run through the basic tutorials on the Steem blockchain and will focus more on the specific functions and outputs pertinent to this topic.</p>

<h2 id="steps">Steps</h2>

<ol>
  <li><a href="#BTO"><strong>Blocks, transactions and operations</strong></a></li>
  <li><a href="#V-ops"><strong>Virtual operation streaming</strong></a></li>
</ol>

<h4 id="1-blocks-transactions-and-operations-">1. Blocks, transactions and operations <a name="BTO"></a></h4>

<p>In order to stream a block and get the information as will be shown below we use the <code class="highlighter-rouge">blockchain api</code> in the <code class="highlighter-rouge">dsteem</code> library. The below method has an option parameter <code class="highlighter-rouge">mode</code> that defaults to <code class="highlighter-rouge">irreversible</code> but can be set to <code class="highlighter-rouge">latest</code> which would then return the <code class="highlighter-rouge">head block</code>. This means that both types of blocks can be streamed.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">stream</span> <span class="o">=</span> <span class="nx">client</span><span class="p">.</span><span class="nx">blockchain</span><span class="p">.</span><span class="nx">getBlockStream</span><span class="p">();</span>
    <span class="nx">stream</span>
        <span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">data</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">block</span><span class="p">)</span> <span class="p">{</span>
            <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">block</span><span class="p">);</span>
            <span class="p">...</span>
            <span class="p">...</span>
</code></pre></div></div>

<p>Below is an example of what a block looks like:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"block_id"</span><span class="p">:</span><span class="s2">"017fa2a9b142cd8d3607b7e7421412402bf97957"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"extensions"</span><span class="p">:[],</span><span class="w">
  </span><span class="nl">"previous"</span><span class="p">:</span><span class="s2">"017fa2a867978140e7553bbfd65396a5a8136d53"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"signing_key"</span><span class="p">:</span><span class="s2">"STM5gBt5xvdb5vhmXjBqfzQ7vwr4hFF5rjmYmZnSbzdb9eWmk9or5"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"timestamp"</span><span class="p">:</span><span class="s2">"2018-08-17T08:31:48"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"transaction_ids"</span><span class="p">:</span><span class="w"> </span><span class="p">[],</span><span class="w">
  </span><span class="nl">"transaction_merkle_root"</span><span class="p">:</span><span class="s2">"4f0d61928ce9595aec6558fb53f1af1b8de06d78"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"transactions"</span><span class="p">:</span><span class="w"> </span><span class="p">[],</span><span class="w">
  </span><span class="nl">"witness"</span><span class="p">:</span><span class="s2">"smooth.witness"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"witness_signature"</span><span class="p">:</span><span class="s2">"204e00e747ce75b24fc26b5d18f12992197c61de0bf27c830416761bd25648238239c5eb26a5e392d474e27c601842e2ccf105ffb47f5a5712727412a18f106dbb"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>Each block contains transactions:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"block_num"</span><span class="p">:</span><span class="w"> </span><span class="mi">25141929</span><span class="p">,</span><span class="w">
  </span><span class="nl">"expiration"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2018-08-17T08:41:42"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"extensions"</span><span class="p">:</span><span class="w"> </span><span class="p">[],</span><span class="w">
  </span><span class="nl">"operations"</span><span class="p">:</span><span class="w"> </span><span class="p">[],</span><span class="w">
  </span><span class="nl">"ref_block_num"</span><span class="p">:</span><span class="w"> </span><span class="mi">41616</span><span class="p">,</span><span class="w">
  </span><span class="nl">"ref_block_prefix"</span><span class="p">:</span><span class="w"> </span><span class="mi">3838737669</span><span class="p">,</span><span class="w">
  </span><span class="nl">"signatures"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"1f261ccf59131dcd10334a40b8b76bd2e80b05eee1c8deaedb…ebb7e4a4d6e22f7823940248f1488978d4ec8ecbd8abbd88e"</span><span class="p">],</span><span class="w">
  </span><span class="nl">"transaction_id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"a972aef3388908f8a4b4a8d889fb89c83d2b8eb3"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"transaction_num"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>And each transaction contains operations:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="w">
  </span><span class="s2">"vote"</span><span class="p">,</span><span class="w"> 
  </span><span class="p">{</span><span class="w">
    </span><span class="nl">"author"</span><span class="p">:</span><span class="s2">"skmedia"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"permlink"</span><span class="p">:</span><span class="s2">"buynearn-new-mlm-plan-launched-4th-june-2018-new-mlm-plan-2018-10inr-4-buynearn-online"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"voter"</span><span class="p">:</span><span class="s2">"nazann"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"weight"</span><span class="p">:</span><span class="mi">4700</span><span class="w">  
  </span><span class="p">}</span><span class="w">
</span><span class="p">]</span><span class="w">
</span></code></pre></div></div>

<h4 id="2-virtual-operation-streaming-">2. Virtual operation streaming <a name="V-ops"></a></h4>

<p>Virtual operations (curation rewards, etc) are derived from blockchain activity, but aren’t actually stored as operations themselves. They happen based on consensus from the blockchain based on other user initiated operations. These <code class="highlighter-rouge">virtual operations</code> are <strong>NOT</strong> available on the <code class="highlighter-rouge">head block</code>, so a 100% live feed of this information would not be possible. In order then to follow these operations you would have to stream the <code class="highlighter-rouge">last_irreversible_block</code>. To get a feed of virtual operations, each of the block transactions needs to be investigated for the <code class="highlighter-rouge">type</code> of the operations.</p>

<p><code class="highlighter-rouge">steem-python</code> provides a very simple method to stream virtual or any other operations directly:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">steem</span> <span class="kn">import</span> <span class="n">Steem</span>
<span class="kn">from</span> <span class="nn">steem.blockchain</span> <span class="kn">import</span> <span class="n">Blockchain</span>
<span class="kn">import</span> <span class="nn">pprint</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">Steem</span><span class="p">()</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">Blockchain</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>

<span class="k">for</span> <span class="n">op</span> <span class="ow">in</span> <span class="n">b</span><span class="o">.</span><span class="n">stream</span><span class="p">(</span><span class="s">'author_reward'</span><span class="p">):</span>
    <span class="n">pprint</span><span class="o">.</span><span class="n">pprint</span><span class="p">(</span><span class="n">op</span><span class="p">)</span>
    <span class="c1"># break
</span></code></pre></div></div>

<p>With result:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"_id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"11cb40b9283c8a89ed5d8c348cbc68d76a9d8bd3"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"author"</span><span class="p">:</span><span class="w"> </span><span class="s2">"hopehash"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"block_num"</span><span class="p">:</span><span class="w"> </span><span class="mi">25145619</span><span class="p">,</span><span class="w">
  </span><span class="nl">"permlink"</span><span class="p">:</span><span class="w"> </span><span class="s2">"hopehash-btc-1-057"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"sbd_payout"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0.000 SBD"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"steem_payout"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2.341 STEEM"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"timestamp"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2018-08-17T17:11:36.18"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"trx_id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0000000000000000000000000000000000000000"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"author_reward"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"vesting_payout"</span><span class="p">:</span><span class="w"> </span><span class="s2">"4740.455508 VESTS"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>From the above example all operations of type “author_reward” will be printed on the console/terminal. You can change the type to which ever operation you want to stream or remove the parameter and stream all operations. The same logic can be followed when using <code class="highlighter-rouge">steem-js</code> by isolating the operations of each transaction and looking for the required operation type. Below example is again a modification of the tutorial initially referenced.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">stream</span> <span class="o">=</span> <span class="nx">client</span><span class="p">.</span><span class="nx">blockchain</span><span class="p">.</span><span class="nx">getBlockStream</span><span class="p">();</span>
    <span class="nx">stream</span>
        <span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">data</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">block</span><span class="p">)</span> <span class="p">{</span>
            <span class="kd">let</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">0</span>
            <span class="k">while</span> <span class="p">(</span><span class="nx">x</span> <span class="o">&lt;</span> <span class="nx">block</span><span class="p">.</span><span class="nx">transactions</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="p">{</span>
                <span class="k">if</span> <span class="p">(</span><span class="nx">block</span><span class="p">.</span><span class="nx">transactions</span><span class="p">[</span><span class="nx">x</span><span class="p">].</span><span class="nx">operations</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">author_reward</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
                    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">block</span><span class="p">.</span><span class="nx">transactions</span><span class="p">[</span><span class="nx">x</span><span class="p">].</span><span class="nx">operations</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
                <span class="p">}</span>
                <span class="nx">x</span> <span class="o">+=</span> <span class="mi">1</span>
            <span class="p">}</span>
        <span class="p">});</span>
</code></pre></div></div>

<p>That’s all there is to it.</p>

</section>

</div>
<div class="footer">
  <a href="#">Back to top</a>
</div>
<script>
    document.getElementById("open-nav").addEventListener("click", function () {
        document.body.classList.toggle("nav-open");
    });
</script>
</body>
</html>


<script src="/js/adjust.js"></script>

